﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using ControlCenter.Model;
using ControlCenter.Model.WebApiDto;
using ControlCenter.Operation;
using MingYuanYun.Context.Abstractions;
using MingYuanYun.Exception;

namespace ControlCenter.ApplicationService
{
    /// <summary>
    /// 机器人执行结果回调服务
    /// </summary>
    public class ResultCallbackService : ApplicationServiceBase, IResultCallbackService
    {
        private readonly IResultCallbackOperation _resultCallbackOperation;
        private readonly IPackageManagementOperation _iPackageManagementOperation;
        private readonly ILogOperation _iLogOperation;

        /// <summary>
        /// 类初始化
        /// </summary>
        /// <param name="context"></param>
        public ResultCallbackService(IServiceContext context) : base(context)
        {
            _resultCallbackOperation = this.GetService<IResultCallbackOperation>();
            _iPackageManagementOperation = this.GetService<IPackageManagementOperation>();
            _iLogOperation = this.GetService<ILogOperation>();
        }

        /// <summary>
        /// 安装结果回调，失败后更新
        /// </summary>
        /// <param name="installPackageCallbackDto">请求参数DTO</param>
        /// <returns></returns>
        public async Task<bool> InstallPackageCallback(InstallPackageCallbackDto installPackageCallbackDto)
        {
            UpdatePackageStatusDto updateDto = new UpdatePackageStatusDto
            {
                RobotId = installPackageCallbackDto.RobotId,
                packageId = installPackageCallbackDto.PackageId,
                packageStatus = installPackageCallbackDto.Status,
                IsInstall = true
            };
            return await _iPackageManagementOperation.UpdatePackageStatus(updateDto);
        }

        /// <summary>
        /// 任务日志回调
        /// </summary>
        /// <param name="executionCallbackDto">请求参数DTO</param>
        /// <returns></returns>
        public async Task<bool> ExecutionPackageCallback(ExecutionCallbackDto executionCallbackDto)
        {
            //参数校验
            ValidateExecutionPackageCallback(executionCallbackDto);

            //保存回调结果
            var isSuccess = await _resultCallbackOperation.ExecutionPackageCallback(executionCallbackDto);
            if (isSuccess)
            {
                try
                {
                    //更新包状态, 更新执行完成(成功或失败)的应用状态为空闲
                    if (executionCallbackDto.Status == ExecutionStatus.Success ||
                        executionCallbackDto.Status == ExecutionStatus.Fail)
                    {
                        _iPackageManagementOperation.UpdateRobotPackagePackageStatus(executionCallbackDto.RpId, (int)PackageStatus.Normal, (int)PackageStatus.Stop);
                    }

                    //写心跳日志
                    var heartLogs = new List<HeartLog>();
                    heartLogs.Add(new HeartLog { HeartType = HeartTypeEnum.Robot, ObjectId = executionCallbackDto.RobotId, Time = DateTime.Now });
                    heartLogs.Add(new HeartLog { HeartType = HeartTypeEnum.PackageTask, ObjectId = executionCallbackDto.RpId, Time = DateTime.Now });
                    await _iLogOperation.BatchAddHeartLogs(heartLogs);
                }
                catch (Exception e)
                {
                    //更新状态或写日志失败时不抛异常，只记日志
                }
            }

            return isSuccess;
        }

        #region 私有方法
        /// <summary>
        /// 任务日志回调前参数校验
        /// </summary>
        /// <param name="executionCallbackDto"></param>
        private void ValidateExecutionPackageCallback(ExecutionCallbackDto executionCallbackDto)
        {
            ExceptionAssert.IsNull(executionCallbackDto, nameof(executionCallbackDto));

            string errorMsg = "";
            if (executionCallbackDto.ExecutionQueueId == Guid.Empty)
            {
                errorMsg += $"{nameof(executionCallbackDto.ExecutionQueueId)} 不能为空；";
            }
            if (executionCallbackDto.RobotId == Guid.Empty)
            {
                errorMsg += $"{nameof(executionCallbackDto.RobotId)} 不能为空；";
            }
            if (executionCallbackDto.PackageId == Guid.Empty)
            {
                errorMsg += $"{nameof(executionCallbackDto.PackageId)} 不能为空；";
            }
            if (executionCallbackDto.Type == ExecutionQueueType.Trace && executionCallbackDto.TraceId == Guid.Empty)
            {
                errorMsg += $"{nameof(executionCallbackDto.TraceId)} 不能为空；";
            }
            if (!string.IsNullOrEmpty(errorMsg))
            {
                throw new BusinessException(errorMsg);
            }
        }
        #endregion
    }
}
